package com.example.demo.match;

import com.example.demo.model.User;
import com.example.demo.room.Room;
import com.example.demo.room.RoomManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
@Slf4j
@Component
//匹配器
public class Matcher {


    //按照玩家天梯分数将玩家分成三个队列
    Queue<User> normalQueue=new LinkedList<>();
    Queue<User> highQueue=new LinkedList<>();
    Queue<User> veryHighQueue=new LinkedList<>();
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;
    private ObjectMapper mapper=new ObjectMapper();
    //按照天梯分数进行玩家匹配,匹配成功放入匹配队列
    public void add(User user){
        if (user.getScore()<2000){
          synchronized (normalQueue){
              normalQueue.offer(user);
              normalQueue.notify();
              log.info("玩家"+user.getUsername()+"加入队列");

          }
        }else if (user.getScore()>=2000&&user.getScore()<3000){
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
                log.info("玩家"+user.getUsername()+"加入队列");
            }
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
                log.info("玩家"+user.getUsername()+"加入队列");
            }
        }
    }

    //玩家点击取消匹配,就从匹配队列移除
    public void remove(User user){
        if (user.getScore()<2000){
           synchronized (normalQueue){
               normalQueue.remove(user);
               log.info("玩家"+user.getUsername()+"移除队列");
           }
        }else if (user.getScore()>=2000&&user.getScore()<3000){
          synchronized (highQueue){
              highQueue.remove(user);
              log.info("玩家"+user.getUsername()+"移除队列");
          }
        }else {
           synchronized (veryHighQueue){
               veryHighQueue.remove(user);
               log.info("玩家"+user.getUsername()+"移除队列");
           }
        }
    }

    //三个线程分别扫描三个队列,处理队列中元素
    public Matcher(){
        Thread t1=new Thread(()->{
           while (true){
               handlerQueue(normalQueue);
           }
        });
        t1.start();
        Thread t2=new Thread(()->{
            while (true){
                handlerQueue(highQueue);
            }
        });
        t2.start();
        Thread t3=new Thread(()->{
           while (true){
               handlerQueue(veryHighQueue);
           }
        });
        t3.start();
    }
    //具体处理,什么时候可以开始一局游戏
    private void handlerQueue(Queue<User> matchQueue) {
        synchronized (matchQueue){
            try {
                while (matchQueue.size()<2){
                    matchQueue.wait();
                }
                //把他俩从队列中移除
                User player1 = matchQueue.poll();
                User player2 = matchQueue.poll();
                log.info("玩家1 player1 {} 玩家2 player2 {}" ,player1,player2);
                //获取当前玩家的webSocket会话,告知对方排到了谁
                WebSocketSession session1=onlineUserManager.getFromGameHall(player1.getUserId());
                WebSocketSession session2=onlineUserManager.getFromGameHall(player2.getUserId());
                if (session1==null){
                    matchQueue.offer(player2);
                    return;
                }
                if (session2==null){
                    matchQueue.offer(player1);
                    return;
                }
                if (session1==session2){
                    matchQueue.offer(player1);
                    return;
                }
                //4.把玩家放入同一个房间中
                Room room=new Room();
                roomManager.add(room, player1.getUserId(), player2.getUserId());

                //5.告知客户端,匹配成功
                MatchResponse response1=new MatchResponse();
                response1.setMessage("matchSuccess");
                response1.setOk(true);
                session1.sendMessage(new TextMessage(mapper.writeValueAsString(response1)));

                MatchResponse response2=new MatchResponse();
                response2.setOk(true);
                response2.setMessage("matchSuccess");
                session2.sendMessage(new TextMessage(mapper.writeValueAsString(response2)));

            }catch (IOException  | InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
